﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Minestorm.Evolved.Animation
{
    public static class EasingTypes
    {
        public static float None(float t, float c, float b, float d)
        {
            return c * t / d + b;
        }

        public static class Regular
        {
            public static float In(float t, float c, float b, float d)
            {
                return c * (t /= d) * t + b;
            }

            public static float Out(float t, float c, float b, float d)
            {
                return -c * (t /= d) * (t - 2) + b;
            }

            public static float InOut(float t, float c, float b, float d)
            {
                if ((t /= d / 2) < 1)
                    return c / 2 * t * t + b;

                return -c / 2 * ((--t) * (t - 2) - 1) + b;
            }
        }

        public static class Bounce
        {
            public static float In(float t, float c, float b, float d)
            {
                var s = 1.70158f;

                return c * (t /= d) * t * ((s + 1) * t - s) + b;
            }

            public static float Out(float t, float c, float b, float d)
            {
                var s = 1.70158f;

                return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
            }

            public static float InOut(float t, float c, float b, float d)
            {
                var s = 1.70158f;

                if ((t /= d / 2) < 1)
                    return c / 2 * (t * t * (((s *= 1.525f) + 1) * t - s)) + b;

                return c / 2 * ((t -= 2) * t * (((s *= 1.525f) + 1) * t + s) + 2) + b;
            }
        }

        public static class Elastic
        {
            public static float In(float t, float c, float b, float d)
            {
                if (t == 0)
                    return b;

                if ((t /= d) == 1)
                    return b + c;

                var p = d * .3f;

                return -(c * (float)Math.Pow(2, 10 * (t -= 1)) * (float)Math.Sin((t * d - (p / 4)) * (2 * MathHelper.Pi) / p)) + b;
            }

            public static float Out(float t, float c, float b, float d)
            {
                if (t == 0)
                    return b;

                if ((t /= d) == 1)
                    return b + c;

                var p = d * .3f;

                return (c * (float)Math.Pow(2, -10 * t) * (float)Math.Sin((t * d - (p / 4)) * (2 * MathHelper.Pi) / p) + c + b);
            }

            public static float InOut(float t, float c, float b, float d)
            {
                if (t == 0)
                    return b;

                if ((t /= d / 2) == 2)
                    return b + c;

                var p = d * .3f;

                if (t < 1)
                    return -.5f * (c * (float)Math.Pow(2, 10 * (t -= 1)) * (float)Math.Sin((t * d - (p / 4)) * (2 * MathHelper.Pi) / p)) + b;

                return c * (float)Math.Pow(2, -10 * (t -= 1)) * (float)Math.Sin((t * d - (p / 4)) * (2 * MathHelper.Pi) / p) * .5f + c + b;
            }
        }

        public static class Strong
        {
            public static float In(float t, float c, float b, float d)
            {
                return c * (t /= d) * t * t * t * t + b;
            }

            public static float Out(float t, float c, float b, float d)
            {
                return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
            }

            public static float InOut(float t, float c, float b, float d)
            {
                if ((t /= d / 2) < 1)
                    return c / 2 * t * t * t * t * t + b;

                return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
            }
        }
    }
}
